export default class Rect{
    ctx: CanvasRenderingContext2D
    x: number
    y: number
    width: number
    height: number
    radius: number | undefined

    preset: number | undefined
    type: 'top' | 'bottom' | undefined

    constructor(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number, radius?: number, preset?: number, type?: 'top' | 'bottom') {
        this.ctx = ctx
        this.x = x
        this.y = y
        this.width = width
        this.height = height
        this.radius = radius
        this.preset = preset
        this.type = type
    }

    drawRect() {
        !this.preset || !this.type
            ? this.radius
                ? this.drawRoundedRect()
                : this.drawNormalRect()
            : this.drawPresetRect()
    }

    private drawPresetRect() {
        const preset = this.preset as number
        const ptA = this.type === 'top'
            ? Rect.Point(this.x + this.width * (1 - preset) / 2, this.y + this.height * (1 - preset) / 2)
            : Rect.Point(this.x, this.y)
        const ptB = this.type === 'top'
            ? Rect.Point(this.x + this.width * (1 + preset) / 2, this.y + this.height * (1 - preset) / 2)
            : Rect.Point(this.x + this.width, this.y)
        const ptC = this.type === 'bottom'
            ? Rect.Point(this.x + this.width * (1 + preset) / 2, this.y + this.height * (1 + preset) / 2)
            : Rect.Point(this.x + this.width, this.y + this.height)
        const ptD = this.type === 'bottom'
            ? Rect.Point(this.x + this.width * (1 - preset) / 2, this.y + this.height * (1 + preset) / 2)
            : Rect.Point(this.x, this.y + this.height)

        this.ctx.beginPath();
        this.ctx.moveTo(ptA.x, ptA.y);

        this.ctx.lineTo(ptB.x, ptB.y);
        this.ctx.lineTo(ptC.x, ptC.y);
        this.ctx.lineTo(ptD.x, ptD.y);
        this.ctx.lineTo(ptA.x, ptA.y);

        this.ctx.closePath()
        this.ctx.stroke();
        this.ctx.fill()
    }

    private drawNormalRect() {
        this.ctx.beginPath();

        this.ctx.rect(this.x, this.y, this.width, this.height);

        this.ctx.stroke();
        this.ctx.fill()
    }

    private drawRoundedRect() {
        const radius = this.radius as number
        const ptA = Rect.Point(this.x + radius, this.y);
        const ptB = Rect.Point(this.x + this.width, this.y);
        const ptC = Rect.Point(this.x + this.width, this.y + this.height);
        const ptD = Rect.Point(this.x, this.y + this.height);
        const ptE = Rect.Point(this.x, this.y);

        this.ctx.beginPath();

        this.ctx.moveTo(ptA.x, ptA.y);
        this.ctx.arcTo(ptB.x, ptB.y, ptC.x, ptC.y, radius);
        this.ctx.arcTo(ptC.x, ptC.y, ptD.x, ptD.y, radius);
        this.ctx.arcTo(ptD.x, ptD.y, ptE.x, ptE.y, radius);
        this.ctx.arcTo(ptE.x, ptE.y, ptA.x, ptA.y, radius);

        this.ctx.stroke();
        this.ctx.fill()
    }

    private static Point(x: number, y: number) {
        return {x:x, y:y};
    };

}
